package org.jsola.hr.service.impl;

import org.jsola.common.DateKit8;
import org.jsola.core.Page;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.ExcelKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.ISalaryTableDAO;
import org.jsola.hr.dto.SalaryTableAddDTO;
import org.jsola.hr.dto.SalaryTableUpdateDTO;
import org.jsola.hr.entity.SalaryBillFieldsDO;
import org.jsola.hr.entity.SalaryTableDO;
import org.jsola.hr.exception.HrException;
import org.jsola.hr.query.SalaryBillSendRelQuery;
import org.jsola.hr.query.SalaryTableExportQuery;
import org.jsola.hr.query.SalaryTableQuery;
import org.jsola.hr.service.ISalaryBillSendService;
import org.jsola.hr.service.ISalaryTableService;
import org.jsola.hr.vo.SalaryBillListVO;
import org.jsola.hr.vo.SalaryTableListVO;
import org.jsola.hr.vo.SalaryTableVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 工资表（工资条统计）
 *
 * @author zhr
 */
@Service("hrSalaryTableServiceImpl")
public class SalaryTableServiceImpl implements ISalaryTableService {

    @Autowired
    private ISalaryTableDAO salaryTableDAO;

    @Autowired
    private ISalaryBillSendService salaryBillSendService;

    /**
     * 序号
     */
    private static final String INDEX = "序号";
    /**
     * 工号
     */
    private static final String JOB_NUMBER = "工号";

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public SalaryTableVO save(SalaryTableAddDTO salaryTableAddDTO, TokenUser tokenUser) {
        // 转DO
        SalaryTableDO salaryTableDO = salaryTableAddDTO.to(SalaryTableDO.class);
        // 保存
        salaryTableDO = save(salaryTableDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return salaryTableDO.to(SalaryTableVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(SalaryTableUpdateDTO salaryTableUpdateDTO, TokenUser tokenUser) {
        //转DO
        SalaryTableDO salaryTableDO = salaryTableUpdateDTO.to(SalaryTableDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(salaryTableDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... salaryTableIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) salaryTableIds);
    }


    @Override
    public SalaryTableVO selectById(String salaryTableId, String siteId) {
        SalaryTableDO salaryTableDO = selectDOById(salaryTableId, siteId);
        if (salaryTableDO == null) {
            return null;
        }
        return salaryTableDO.to(SalaryTableVO.class);
    }

    @Override
    public List<SalaryTableListVO> select(SalaryTableQuery salaryTableQuery, String siteId) {
        List<SalaryTableDO> salaryTableDOList = selectDO(salaryTableQuery, siteId);
        if(CollectionUtils.isEmpty(salaryTableDOList)) {
            return salaryTableDOList == null ? null : new ArrayList<>();
        }
        return salaryTableDOList.stream()
                .map(salaryTableDO -> salaryTableDO.to(SalaryTableListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(SalaryTableQuery salaryTableQuery, String siteId) {
        Example example = buildExample(salaryTableQuery,siteId);
        return salaryTableDAO.selectCountByExample(example);
    }

    @Override
    public Page<SalaryTableListVO> selectPage(SalaryTableQuery salaryTableQuery, String siteId) {
        Example example = buildExample(salaryTableQuery,siteId);
        Page<SalaryTableDO> page = salaryTableDAO.selectPageByExample(example,
                salaryTableQuery.getPageNo(),
                salaryTableQuery.getPageSize());

        return page.to(SalaryTableListVO.class);
    }

    @Override
    public SalaryTableDO selectDOById(String salaryTableId, String siteId) {
        return listById(salaryTableId, siteId);
    }

    @Override
    public List<SalaryTableDO> selectDO(SalaryTableQuery salaryTableQuery, String siteId) {
        Example example = buildExample(salaryTableQuery,siteId);
        return salaryTableDAO.selectByExample(example);
    }


    /**
     * 根据查询参数，构建example

     * @param salaryTableQuery 查询参数
     * @param siteId 所属站点id
     * @return example
     */
    private Example buildExample(SalaryTableQuery salaryTableQuery, String siteId) {
        Example example = new Example(SalaryTableDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (salaryTableQuery.getTableName() != null) {
            example.and().andEqualTo("tableName", salaryTableQuery.getTableName());
        }
        if (salaryTableQuery.getYear() != null) {
            example.and().andEqualTo("year", salaryTableQuery.getYear());
        }
        if (salaryTableQuery.getMonth() != null) {
            example.and().andEqualTo("month", salaryTableQuery.getMonth());
        }
        if (salaryTableQuery.getCompanyId() != null) {
            example.and().andEqualTo("companyId", salaryTableQuery.getCompanyId());
        }
        // 排序
        ExampleKit.setExampleOrder(example,salaryTableQuery.getOrders());
        return example;
    }

    @Override
    public Map<String, List<SalaryTableListVO>> listAllRelation(SalaryTableQuery salaryTableQuery, String siteId) {
        List<SalaryTableListVO> salaryTableListVOList = salaryTableDAO.listAllRelation(salaryTableQuery, siteId);
        Map<String, List<SalaryTableListVO>> salaryTableListVOMap = new HashMap<>();

        if(CollectionUtils.isEmpty(salaryTableListVOList)) {
            return salaryTableListVOMap;
        }

        salaryTableListVOList.forEach(salaryTableListVO -> {
            // map中是否包含当前月的key
            if(salaryTableListVOMap.containsKey(salaryTableListVO.getMonth())){
                salaryTableListVOMap.get(salaryTableListVO.getMonth()).add(salaryTableListVO);
            }else{
                List<SalaryTableListVO> salaryTableListVOListTmp = new ArrayList<>();
                salaryTableListVOListTmp.add(salaryTableListVO);
                salaryTableListVOMap.put(salaryTableListVO.getMonth(), salaryTableListVOListTmp);
            }
        });

        // map排序
//        Map<String, List<SalaryTableListVO>> salaryTableListVOMapOrder = new HashMap<>();
////        salaryTableListVOMap.entrySet().stream()
////                .sorted(Map.Entry.comparingByKey())
////                .forEachOrdered(x->salaryTableListVOMapOrder.put(x.getKey(),x.getValue()));
//
//        salaryTableListVOMapOrder = salaryTableListVOMap.entrySet()
//                .stream()
//                .sorted((Map.Entry.<String, List<SalaryTableListVO>>comparingByKey((o1, o2) -> Integer.valueOf(o1)).reversed()))
//                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));

        return salaryTableListVOMap;
    }

    @Override
    public List<String> salaryTableImportedYearList(SalaryTableQuery salaryTableQuery, String siteId){
        return salaryTableDAO.salaryTableImportedYearList(salaryTableQuery, siteId);
    }

    @Override
    public List<SalaryTableListVO> salaryTableGroupByEmpId(SalaryTableQuery salaryTableQuery, String siteId){
        return salaryTableDAO.salaryTableGroupByEmpId(salaryTableQuery, siteId);
    }

    @Override
    public List<SalaryTableListVO> salaryTableGroupByMonthEmpId(SalaryTableQuery salaryTableQuery, String siteId){
        return salaryTableDAO.salaryTableGroupByMonthEmpId(salaryTableQuery, siteId);
    }

    @Override
    public String salaryTableExport(SalaryTableExportQuery salaryTableExportQuery,String siteId){
        //根据工资表查询工资表下的人员
        SalaryBillSendRelQuery salaryBillSendRelQuery = new SalaryBillSendRelQuery();
        salaryBillSendRelQuery.setTableId(salaryTableExportQuery.getTableId());
        List<SalaryBillListVO> salaryBillListVOList = salaryBillSendService.allSalaryBillSendDetail(salaryBillSendRelQuery, siteId);
        if(CollectionUtils.isEmpty(salaryBillListVOList)){
            throw new HrException("暂无人员可导出");
        }
        Map<String, Object> headMap = new HashMap<>(8);
        //把表中只需要填充一次的数据存储起来
        headMap.put("tableName",salaryTableExportQuery.getTableName());
        headMap.put("empCount",salaryTableExportQuery.getEmpCount());
        headMap.put("salaryAmountTotal",salaryTableExportQuery.getSalaryAmountTotal());
        headMap.put("sendCount",salaryTableExportQuery.getReadCount());
        headMap.put("feedbackCount",salaryTableExportQuery.getFeedbackCount());
        //表头定义
        List <List<String>> headList = new ArrayList<>();
        List<String> allHead = new ArrayList<>();
        allHead.add("姓名");
        allHead.add("发放方式");
        allHead.add("发放时间");
        allHead.add("是否已确认工资条");
        allHead.add("基本工资");
        allHead.add("考勤扣款");
        allHead.add("应发工资");
        allHead.add("个人社保");
        allHead.add("个人公积金");
        allHead.add("个人所得税");
        allHead.add("实发工资");
        //额外自定义项表头
        for (SalaryBillFieldsDO salaryBillFieldsDO : salaryBillListVOList.get(0).getSalaryBillFieldsDOList()) {
            if (INDEX.equals(salaryBillFieldsDO.getFieldName())) {
                allHead.add(0, salaryBillFieldsDO.getFieldName());
                continue;
            }
            if (JOB_NUMBER.equals(salaryBillFieldsDO.getFieldName())) {
                allHead.add(0, salaryBillFieldsDO.getFieldName());
                continue;
            }
            allHead.add(salaryBillFieldsDO.getFieldName());
        }
        headList.add(allHead);
        //数据
        List<List<String>> dateList = new ArrayList<>();
        for (SalaryBillListVO salaryBillListVO : salaryBillListVOList) {
            List <String> oneDate = new ArrayList<>();
            fillList(oneDate,salaryBillListVO);
            //额外自定义项数据
            for (SalaryBillFieldsDO salaryBillFieldsDO : salaryBillListVO.getSalaryBillFieldsDOList()) {
                if (INDEX.equals(salaryBillFieldsDO.getFieldName())) {
                    oneDate.add(0, salaryBillFieldsDO.getFieldValue());
                    continue;
                }
                if (JOB_NUMBER.equals(salaryBillFieldsDO.getFieldName())) {
                    oneDate.add(0, salaryBillFieldsDO.getFieldValue());
                    continue;
                }
                oneDate.add(salaryBillFieldsDO.getFieldValue());
            }
            dateList.add(oneDate);
        }
        return ExcelKit.complexExportExcel("salaryBill", "工资条", headList, dateList, headMap);
    }
    private void fillList(List <String> oneDate,SalaryBillListVO salaryBillListVO){
        if (salaryBillListVO.getEmpName() != null) {
            oneDate.add(salaryBillListVO.getEmpName());
        } else {
            oneDate.add("");
        }
        if (salaryBillListVO.getSendType() != null) {
            switch (salaryBillListVO.getSendType()){
                case 1: oneDate.add("微信");
                    break;
                case 2: oneDate.add("短信");
                    break;
                default: oneDate.add("");
            }
        } else {
            oneDate.add("");
        }
        if (salaryBillListVO.getSendTime() != null) {
            oneDate.add(DateKit8.format2Date(salaryBillListVO.getSendTime()));
        } else {
            oneDate.add("");
        }
        if (salaryBillListVO.getCheckStatus() != null) {
            switch (salaryBillListVO.getCheckStatus().toString()){
                case "true": oneDate.add("已确认");
                    break;
                case "false": oneDate.add("未确认");
                    break;
                default: oneDate.add("");
            }
        } else {
            oneDate.add("");
        }
        if (salaryBillListVO.getSalaryBasic() != null) {
            oneDate.add(salaryBillListVO.getSalaryBasic().toString());
        } else {
            oneDate.add("");
        }
        if (salaryBillListVO.getDeduction() != null) {
            oneDate.add(salaryBillListVO.getDeduction().toString());
        } else {
            oneDate.add("");
        }
        if (salaryBillListVO.getSalaryAmount() != null) {
            oneDate.add(salaryBillListVO.getSalaryAmount().toString());
        } else {
            oneDate.add("");
        }
        if (salaryBillListVO.getEmpSoc() != null) {
            oneDate.add(salaryBillListVO.getEmpSoc().toString());
        } else {
            oneDate.add("");
        }
        if (salaryBillListVO.getEmpPf() != null) {
            oneDate.add(salaryBillListVO.getEmpPf().toString());
        } else {
            oneDate.add("");
        }
        if (salaryBillListVO.getEmpTax() != null) {
            oneDate.add(salaryBillListVO.getEmpTax().toString());
        } else {
            oneDate.add("");
        }
        if (salaryBillListVO.getSalaryReal() != null) {
            oneDate.add(salaryBillListVO.getSalaryReal().toString());
        } else {
            oneDate.add("");
        }
    }
}




